package com.blog.cmrpersonalblog.strategy.upload;

import com.blog.cmrpersonalblog.config.FileUploadConfig;
import com.blog.cmrpersonalblog.dto.file.respnose.FileUploadResponse;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * 文件上传策略抽象基类
 * 提供通用的文件上传逻辑
 */
@Slf4j
public abstract class AbstractFileUploadStrategy implements FileUploadStrategy {
    
   @Resource
    protected FileUploadConfig fileUploadConfig;
    
    /**
     * 支持的图片格式
     */
    protected static final List<String> SUPPORTED_IMAGE_TYPES = Arrays.asList(
        "jpg", "jpeg", "png", "gif", "bmp", "webp"
    );
    
    /**
     * 支持的文档格式
     */
    protected static final List<String> SUPPORTED_DOCUMENT_TYPES = Arrays.asList(
        "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx", "txt"
    );
    
    @Override
    public FileUploadResponse upload(MultipartFile file, Long userId, Object... extraParams) {
        try {
            // 验证文件
            if (!validateFile(file)) {
                throw new RuntimeException("文件验证失败");
            }
            
            // 生成文件名
            String fileName = generateFileName(file.getOriginalFilename(), userId, extraParams);
            
            // 构建完整路径
            String fullPath = buildFullPath();
            
            // 创建目录
            createDirectoryIfNotExists(fullPath);
            
            // 保存文件
            Path filePath = Paths.get(fullPath, fileName);
            Files.copy(file.getInputStream(), filePath);
            
            // 构建相对路径
            String relativePath = getSupportedType().getRelativePath() + "/" + fileName;
            
            // 构建访问URL
            String fileUrl = buildFileUrl(relativePath);
            
            // 创建响应
            FileUploadResponse response = new FileUploadResponse();
            response.setFileName(fileName);
            response.setOriginalFileName(file.getOriginalFilename());
            response.setFileSize(file.getSize());
            response.setContentType(file.getContentType());
            response.setFileUrl(fileUrl);
            response.setRelativePath(relativePath);
            response.setUploadTime(System.currentTimeMillis());
            
            log.info("文件上传成功: type={}, fileName={}, size={}", 
                getSupportedType().getDescription(), fileName, file.getSize());
            
            return response;
            
        } catch (IOException e) {
            log.error("文件上传失败: type={}, error={}", 
                getSupportedType().getDescription(), e.getMessage(), e);
            throw new RuntimeException("文件上传失败：" + e.getMessage());
        }
    }
    
    @Override
    public boolean isValidFileType(MultipartFile file) {
        String extension = getFileExtension(file.getOriginalFilename());
        return SUPPORTED_IMAGE_TYPES.contains(extension.toLowerCase());
    }
    
    @Override
    public String generateFileName(String originalFileName, Long userId, Object... extraParams) {
        String extension = getFileExtension(originalFileName);
        String timestamp = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String uuid = UUID.randomUUID().toString().replace("-", "").substring(0, 8);
        
        StringBuilder fileName = new StringBuilder();
        fileName.append(getSupportedType().getCode()).append("_");
        
        if (userId != null) {
            fileName.append("user").append(userId).append("_");
        }
        
        fileName.append(timestamp).append("_").append(uuid);
        
        if (StringUtils.hasText(extension)) {
            fileName.append(".").append(extension);
        }
        
        return fileName.toString();
    }
    
    @Override
    public boolean deleteFile(String relativePath) {
        try {
            if (!StringUtils.hasText(relativePath)) {
                return false;
            }
            
            Path filePath = Paths.get(fileUploadConfig.getBasePath(), relativePath);
            if (Files.exists(filePath)) {
                Files.delete(filePath);
                log.info("文件删除成功: {}", relativePath);
                return true;
            } else {
                log.warn("要删除的文件不存在: {}", relativePath);
                return false;
            }
        } catch (IOException e) {
            log.error("文件删除失败: path={}, error={}", relativePath, e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 构建完整路径
     */
    protected String buildFullPath() {
        return fileUploadConfig.getBasePath() + getSupportedType().getRelativePath();
    }
    
    /**
     * 构建文件访问URL
     */
    protected String buildFileUrl(String relativePath) {
        return fileUploadConfig.getFileUrl(relativePath);
    }
    
    /**
     * 创建目录（如果不存在）
     */
    protected void createDirectoryIfNotExists(String dirPath) {
        File dir = new File(dirPath);
        if (!dir.exists()) {
            boolean created = dir.mkdirs();
            if (!created) {
                throw new RuntimeException("创建上传目录失败: " + dirPath);
            }
        }
    }
    
    /**
     * 获取文件扩展名
     */
    protected String getFileExtension(String fileName) {
        if (!StringUtils.hasText(fileName)) {
            return "";
        }
        
        int lastDotIndex = fileName.lastIndexOf('.');
        if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) {
            return fileName.substring(lastDotIndex + 1);
        }
        
        return "";
    }
}
